#include "propertyeditor.h"

#include "../guicommon.h"
#include "delegates/comboboxdelegate.h"
#include "delegates/completerdelegate.h"
#include "delegates/lineeditdelegate.h"

#include <validatormanager.h>

#include <QtGui/QHeaderView>

using namespace core;
using namespace gui;

PropertyEditor::PropertyEditor(QWidget* parent) : QTableView(parent),
    m_object(0),
    m_model(new QStandardItemModel(this)),
    m_headerLabels(),
    m_listDelegate(0),
    m_completerDelegate(0),
    m_stringDelegate(0)
{
    m_headerLabels << tr("Name") << tr("Value");
    m_model->setHorizontalHeaderLabels(m_headerLabels);

    m_listDelegate = new ComboBoxDelegate(this);
    m_completerDelegate = new CompleterDelegate(this);
    m_stringDelegate = new LineEditDelegate(this);
    m_stringDelegate->setValidator(
        ValidatorManager::getInstance()->getValidator(
            STRING_PROPERTY_VALIDATOR));
    m_intDelegate = new LineEditDelegate(this);
    m_intDelegate->setValidator(
        ValidatorManager::getInstance()->getValidator(
            INT_PROPERTY_VALIDATOR));

    setModel(m_model);
    setAlternatingRowColors(true);
    setGridStyle(Qt::NoPen);
    verticalHeader()->hide();
    horizontalHeader()->setStretchLastSection(true);

    connect(m_model, SIGNAL(itemChanged(QStandardItem*)),
        this, SLOT(changeValue(QStandardItem*)));
}

PropertyEditor::~PropertyEditor()
{

}

void PropertyEditor::updateModel()
{
    m_model->clear();

    m_model->setHorizontalHeaderLabels(m_headerLabels);

    if (m_object != 0)
    {
        const QList<Property> properties = m_object->properties();

        QStandardItem* textItem = new QStandardItem(tr("Object name"));
        textItem->setEditable(false);
        textItem->setSelectable(false);
        QStandardItem* valueItem = new QStandardItem(m_object->name());
        valueItem->setEditable(false);
        valueItem->setSelectable(false);

        m_model->setItem(0, 0, textItem);
        m_model->setItem(0, 1, valueItem);

        int row = 1;
        foreach (const Property& property, properties)
        {
            if (property.isVisibleToEditor())
            {
                const QVariant value = property.value();

                const QString text = property.Text;
                const QString _value = value.type() == QVariant::List ?
                    value.toList().first().toString() : value.toString();

                QStandardItem* textItem = new QStandardItem(text);
                textItem->setEditable(false);
                textItem->setSelectable(false);
                QStandardItem* valueItem = new QStandardItem(_value);
                valueItem->setEditable(true);
                valueItem->setData(property.Name, Qt::UserRole);
                QFont font = valueItem->font();
                font.setBold(true);
                valueItem->setFont(font);

                if (property.delegate() != 0)
                {
                    setItemDelegateForRow(row, property.delegate());
                }
                else if (value.type() == QVariant::List)
                {
                    setItemDelegateForRow(row, m_listDelegate);
                }
                else if (m_object->autocomplete(property.Name).size() > 0)
                {
                    setItemDelegateForRow(row, m_completerDelegate);
                }
                else if (value.type() == QVariant::Int)
                {
                    setItemDelegateForRow(row, m_intDelegate);
                }
                else
                {
                    setItemDelegateForRow(row, m_stringDelegate);
                }

                m_model->setItem(row, 0, textItem);
                m_model->setItem(row, 1, valueItem);

                ++row;
            }
        }
    }
}

// public slots
void PropertyEditor::propertyObjectChanged(core::IPropertyObject* object)
{
    if (object != m_object)
    {
        m_object = object;

        updateModel();
    }
}

// private slots
void PropertyEditor::changeValue(QStandardItem* changed)
{
    const QString propertyName = changed->data(Qt::UserRole).toString();

    if (!propertyName.isNull() && !propertyName.isEmpty())
    {
        const QVariant propertyValue = m_object->propertyValue(propertyName);

        Q_ASSERT(propertyValue.isValid());

        QVariant value;

        bool equal = true;
        switch (propertyValue.userType())
        {
            case QVariant::Bool:
                value = QVariant(changed->text()).toBool();
                equal = propertyValue.toBool() == value.toBool();
                break;
            case QVariant::String:
                value = QVariant(changed->text());
                equal = propertyValue.toString() == value.toString();
                break;
            case QVariant::Int:
                value = QVariant(changed->text()).toInt();
                equal = propertyValue.toInt() == value.toInt();
                break;
            case QVariant::Double:
                value = QVariant(changed->text()).toDouble();
                equal = (propertyValue.toDouble() - value.toDouble()) <
                    0.00001;
                break;
            case QVariant::List:
                value = QVariant(changed->text());
                equal = propertyValue.toList().first().toString() ==
                    value.toString();
                break;
            default:
                Q_ASSERT(false); // not supported
                break;
        }

        if (!equal) {
            m_object->propertyChanged(propertyName, value);
        }
    }
}
